/**
 * System:      oshys
 * Model:       log
 * Licence:     GNU General Public License v3
 * Author:      sunwl
 * Date:        2010/02/19
 */
package org.oshys.util.logging;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

import static org.oshys.util.logging.ConfigProvider.getResource;

/**
 * 简单格式化器。<br>
 * 读取配置文件中的格式化配置，并格式化一个消息。<br>
 * 与该格式化器相关的配置项：logging.format
 * @author sunwl
 */
public class SimpleFormatter implements IFormatter {
	
    private static final String LOGGER_CLASS = "org.oshys.util.logging.Logger";
    
    public SimpleFormatter () {
    }
    
    public String format (LogMessage message) {
    	StringBuffer result = new StringBuffer();
		String logFormat = ConfigProvider.getResource("logging.format", "%date%time%level%location%message");
		SimpleDateFormat sdf = new SimpleDateFormat();
		Date date = new Date();
		
		if(logFormat.indexOf("%date") >= 0){
			sdf.applyPattern("yyyy-MM-dd");
			result.append(sdf.format(date));
			result.append(SPACE);
		}
		if(logFormat.indexOf("%time") >= 0){
			sdf.applyPattern("HH:mm:ss,SSS");
			result.append(sdf.format(date));
			result.append(SPACE);
		}
		if(logFormat.indexOf("%level") >= 0){
			result.append(getLocalizedName(message.getLevel()));
			result.append(SPACE);
		}
		if(logFormat.indexOf("%location") >= 0){
			String fileName = null;
			int lineNumber = 0;
			StackTraceElement e = inferCaller();
			if(e != null){
			    fileName = e.getFileName();
	            lineNumber = e.getLineNumber();
			}
			
			result.append("(");
			result.append(fileName == null?"?":fileName);
			result.append(":");
			result.append(lineNumber);
			result.append(") ");
		}
		if(logFormat.indexOf("%message") >= 0){
			result.append(" - ");
			result.append(message.getMessage());
		}
		result.append(LINE_SEPARATOR);
		
		if (message.getThrown() != null) {
		    try {
		        StringWriter sw = new StringWriter();
		        PrintWriter pw = new PrintWriter(sw);
		        message.getThrown().printStackTrace(pw);
		        pw.close();
		        result.append(sw.toString());
		    } catch (Exception ex) {
		    }
		}
		
        return result.toString();
    }
    /**
     * 获取本地语言的级别名称
     * @param level
     * @return 
     */
    private String getLocalizedName(Level level){
    	String key = "logging.level." + level.getName().toLowerCase();
    	return getResource(key);
    }
    
    /**
     * 获取使用Log信息的位置信息。
     * @return
     */
    private StackTraceElement inferCaller() {
        StackTraceElement stack[] = (new Throwable()).getStackTrace();

        int ix = 0;
        while (ix < stack.length) {
            StackTraceElement frame = stack[ix];
            String cname = frame.getClassName();
            if (cname.equals(LOGGER_CLASS)) {
                break;
            }
            ix++;
        }

        while (ix < stack.length) {
            StackTraceElement frame = stack[ix];
            String cname = frame.getClassName();
            if (!cname.equals(LOGGER_CLASS)) {
                return frame;
            }
            ix++;
        }
        return null;
    }
}

